﻿using System;
using System.Collections.Generic;
using Cinemachine;
using GameFramework.Battle.Core;
using OWL.Rendering.HRP;
using UnityEngine;
using UnityEngine.AI;
using Yoozoo.Core.Extensions.Engine;
using Yoozoo.Framework.Core;
using Yoozoo.Gameplay.Liberty;
using Yoozoo.Gta.Common;
using Yoozoo.HRP.Runtime;
using Yoozoo.Managers.ResourceManagerV2.Runtime;

namespace Gameplay.PVE.Survivor
{
    public class MapManager: BattleSingleton<MapManager>
    {
        public bool IsMapReady = false;
		public override void Initialize()
        {
            if (SurvivorManager.isNavMesh)
            {
                navMesh = new NavMeshData();
                NavMesh.AddNavMeshData(navMesh);
            }
        }
        
        private class DynamicNavmeshObject
        {
            public MeshFilter[] meshList;
            public Transform transform;
            public List<int> indexInArray;
        }
        private List<NavMeshBuildSource> staticSourceList = new List<NavMeshBuildSource>();
        private NavMeshData navMesh;
        private MapNavmeshData[] mapData;

        private bool isDynamicScene;
        private LibertySceneManager libertySceneManager;

        private BattleGameObject mapGameObject;

        private NavMeshDataInstance navMeshInstance;
        
        private void SetMapActive(GameObject mapObject,BattleMapScene data)
        {
            mapObject.SetActive(true);
            HRenderSceneManager.Inst.EnableBaseScene(data.renderSettingName);
            BattleConstValue.LightElementMark = data.lightElementName;
            var isNight = BattleHelper.IsNightScene(data.renderSettingName);
            var mapSkyBox = mapObject.GetComponent<MapSkyBox>();
            if (mapSkyBox != null)
            {
                RenderSettings.skybox = isNight ? mapSkyBox.skyBoxMaterialNight : mapSkyBox.skyBoxMaterial;
            }
            StageManager.Instance.SetIsNight(isNight);
            StageManager.Instance.InitLightDirections();
            UnitManager.Instance.OnLightElementChange();
            isDynamicScene = false;
            if (SurvivorManager.isMap)
            {
                libertySceneManager = mapObject.GetComponentInChildren<LibertySceneManager>();
                if (libertySceneManager)
                {
                    libertySceneManager.InitSurvivor(OnSceneObjectReadyToLoad,OnSceneObjectLoadFinish,OnSceneObjectHide);
                    SetSceneDetector(CameraManager.Instance.sceneDetector);
                    libertySceneManager.AddDynamicObject();
                    libertySceneManager.SetSync(true);
                    CameraManager.Instance.SetDetectorPosition(StageManager.Instance.centerPoint,100);
                    libertySceneManager.SetSync(false);
                    isDynamicScene = true;
                    if (mustLoadObjectCount == 0)
                    {
                        MapReady();
                    }
                }
                else
                {
                    BattleResourceManager.Instance.LoadComplete(ELoadingResourceType.MapResource);
                }
            }
            else
            {
                MapReady();
                BattleResourceManager.Instance.LoadComplete(ELoadingResourceType.MapResource);
            }
        }

        private int mustLoadObjectCount = 0;
        private Dictionary<SceneObjectInfo,GameObject> mustLoadObjectMap = new Dictionary<SceneObjectInfo,GameObject>();
        
        private void OnSceneObjectReadyToLoad(SceneObjectInfo info)
        {
            if(info.IsNavmeshObject)
            {
                mustLoadObjectCount++;
                //BattleDebug.LogError("必须加载的资源 " + info.GetPrefabPath());
            }
        }

        private void OnSceneObjectLoadFinish(SceneObjectInfo info,GameObject gameObject)
        {
            if (info.IsNavmeshObject)
            {
                mustLoadObjectCount--;
                mustLoadObjectMap.Add(info,gameObject);
                //BattleDebug.LogError("必须加载的资源回来了 剩余 "+ mustLoadObjectCount + " " + info.GetPrefabPath());
                if (mustLoadObjectCount <= 0)
                {
                    //RebuildNavmesh();
                    //MapReady();
                    //RebuildNavmeshByAsset("Assets/ResourcesAssets/Pve/Survivor/Navmesh/NavMesh.asset");
                    BattleResourceManager.Instance.LoadComplete(ELoadingResourceType.MapResource);
                    ResidentHandler.Inst.GetFunction("L_SurvivorManager.EndTransfer").Action();
                }
            }
        }

        private ResLoader navMeshDataLoader;

        public void RebuildNavmeshByAsset(NavMeshData navMeshData)
        {
            if (navMeshData == null)
            {
                BattleDebug.LogError("重建navmesh失败");
                MapReady();
                return;
            }
            /*if (navMeshDataLoader == null)
            {
                navMeshDataLoader = ResLoader.Alloc();
            }
            navMeshDataLoader.Add2Load(path,(isSuccess,name,obj)=>
            {
                BattleDebug.LogError(obj);
                if (isSuccess)
                {
                    var data = obj as NavMeshData;
                    NavMesh.AddNavMeshData(data);
                    BattleDebug.LogError("重建navmesh成功");
                    MapReady();
                }
            });
            navMeshDataLoader.Load();*/
            if (SurvivorManager.isNavMesh)
            {
                navMeshInstance = NavMesh.AddNavMeshData(navMeshData);
            }
            MapReady();
        }

        private void OnSceneObjectHide(SceneObjectInfo info)
        {
            mustLoadObjectMap.Remove(info);
        }
        

       /*static Vector3 Quantize(Vector3 v, Vector3 quant)
        {
             float x = quant.x * Mathf.Floor(v.x / quant.x);
             float y = quant.y * Mathf.Floor(v.y / quant.y);
             float z = quant.z * Mathf.Floor(v.z / quant.z);
             return new Vector3(x, y, z);
        }
 
        Bounds QuantizedBounds()
        {
            // Quantize the bounds to update only when theres a 10% change in size
             var center = m_Tracked ? m_Tracked.position : transform.position;
            return new Bounds(Quantize(center, 0.1f * m_Size), m_Size);
        }*/
       private void MapReady()
       {
          IsMapReady = true;
          UnitManager.Instance.OnMapReady();
          BattleResourceManager.Instance.LoadComplete(ELoadingResourceType.MapNavMesh);
          if (DeckManager.Instance.IsInDeck)
          {
              DeckManager.Instance.OnMapReady();
          }
       }
       

       public void OnStageChanged(string mapName)
       {
           //SetMapActive(mapName);
       }
       
        public void LoadMap(BattleMapScene scene)
        {
            var name = scene.mapPrefabName;
            var path = "Assets/ResourcesAssets/Pve/Survivor/Prefabs/" + name + ".prefab";
            mapGameObject = BattlePoolManager.Instance.Get(path, (gameObject)=>
            {
                SetMapActive(gameObject,scene);
            });
            mapGameObject.Parent = SurvivorManager.Instance.Root;
        }

        public void AddCollider()
        {
            /*for (int i = 0; i < mapData.Length; i++)
            {
                var mapNavmeshData = mapData[i];
                for (int j = 0; j < mapNavmeshData.meshList.Count; j++)
                {
                    var meshFilter = mapNavmeshData.meshList[j];
                    var collider = meshFilter.gameObject.GetOrAddComponent<BoxCollider>();
                    meshFilter.SetLayer(BattleConstValue.SurvivorObstacleLayer);
                }
            }*/
        }

        private Vector3 navmeshCenter = BattleConstValue.DEFAULT_POINT;

        public override void Update()
        {
           
        }
        
        private void RebuildNavmesh()
        {
            var sourceList = new List<NavMeshBuildSource>();
            foreach(var item in mustLoadObjectMap)
            {
                var meshFilter = item.Value.GetComponentInChildren<MeshFilter>();
                if (meshFilter)
                {
                    var mesh = meshFilter.sharedMesh;
                    if (mesh == null)
                    {
                        continue;
                    }
                    if (!mesh.isReadable)
                    {
                        BattleDebug.LogError(mesh.name + " is not readable");
                        continue;
                    }
                    sourceList.Add(new NavMeshBuildSource
                    {
                        shape = NavMeshBuildSourceShape.Mesh,
                        area = 0,
                        transform = meshFilter.transform.localToWorldMatrix,
                        sourceObject = meshFilter.sharedMesh,
                        component = meshFilter
                    });
                }
            }
            
            var defaultBuildSettings = NavMesh.GetSettingsByID(NavMesh.GetSettingsByIndex(2).agentTypeID);
            var bounds = new Bounds(CameraManager.Instance.sceneDetector.transform.position, new Vector3(200, 50, 200));
            NavMeshBuilder.UpdateNavMeshData(navMesh, defaultBuildSettings, sourceList, bounds);
        }

        public void SetSceneDetector(SceneTransformDetector detector)
        {
            libertySceneManager.SetSceneDetector(detector);
        }

        public override void Dispose()
        {
            if (SurvivorManager.isNavMesh)
            {
                NavMesh.RemoveNavMeshData(navMeshInstance);
            }
            if (isDynamicScene)
            {
                if (libertySceneManager)
                {
                    libertySceneManager.Dispose();
                    libertySceneManager.UnloadAllDynamicObjects();
                    libertySceneManager = null;
                }
            }
            if (mapGameObject != null)
            {
                mapGameObject.Dispose();
                mapGameObject = null;
            }
            staticSourceList.Clear();
            navMesh = null;
            mapData = null;
            isDynamicScene = false;
            mustLoadObjectCount = 0;
            mustLoadObjectMap.Clear();
            IsMapReady = false;
        }
    }
}
